package com.tb.sng.utils.loader
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	
	/**
	 * 可视化文件加载器
	 * 做了在加载相同文件地址时，只加载一次的处理
	 * 
	 * @author 任冬 rendong01@snda.com
	 * $Id: DisplayLoader.as 9 2012-08-12 17:04:32Z rendong237@gmail.com $
	 * @version 1.0
	 */
	public class DisplayLoader
	{
		
		/**
		 * 当前正在加载的地址 
		 */		
		private var currentLoaderUrl:Object = {};
		/**
		 * 当前正在加载的loader 
		 */		
		private var currentLoader:Dictionary = new Dictionary();
		
		/**
		 * 等待加载的文件队列 文件地址
		 */		
		private static var urlQueue:Vector.<String> = new Vector.<String>();
		
		/**
		 *  等待加载的文件队列 值地址
		 */
		private static var valueQueue:Vector.<Object> = new Vector.<Object>();
		
		/**
		 * 创建唯一实例 
		 */		
		private static var _instance:DisplayLoader = new DisplayLoader();
		
		public function DisplayLoader()
		{
			if (_instance)
				throw new Error("Create DisplayLoader Instance Error");
		}
		
		/**
		 * 获取可视化加载对象
		 *  
		 * @param url			    文件地址
		 * @param successCallback   加载成功后的回调函数，参数为：LoaderInfo
         * @param contextObject  数据相关对象
		 * @param failCallback	    加载失败后的回调函数，参数为：errorMessage
		 * @param progressCallback	进度加载回调函数，参数为：ProgressEvent
		 * @param lc				加载的上下文
		 * @param vars				附加的参数，一般如果考虑版本号，就加这个
		 * 
		 */		
		public static function getLoaderInfo(url:String, successCallback:Function,  failCallback:Function=null, progressCallback:Function=null, lc:LoaderContext=null, vars:URLVariables = null, contextObject:Object = null):void
		{
			_instance._getLoaderInfo(url, successCallback,  failCallback, progressCallback, lc, vars, contextObject);
		}
		
		
		// 真实接口	
		public function _getLoaderInfo(url:String, successCallback:Function, failCallback:Function=null, progressCallback:Function=null, lc:LoaderContext=null, vars:URLVariables = null, contextObject:Object = null):void
		{
			var param:getLoaderInfoParam = new getLoaderInfoParam();
			param.url = url;
			param.successCallback = successCallback;
            param.contextObject = contextObject;
			param.failCallback = failCallback;
			param.progressCallback = progressCallback;
			param.lc = lc;
			param.vars = vars;
			
			// 如果当前文件正在加载，则放入队列
			if (currentLoaderUrl[param.url+param.vars] != null)
			{
				urlQueue.push(url);
				
				valueQueue.push(param);
			}else{
				loadFile(param);
			}
		}
		
		
		/**
		 * 加载文件 
		 * @param param
		 */		
		private function loadFile(param:getLoaderInfoParam):void
		{
			var loader:Loader = new Loader();
			
			param.loader = loader;
			
			currentLoader[loader] = param;
			currentLoaderUrl[param.url+param.vars] = param;
			
			loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
			
			var req:URLRequest = new URLRequest(param.url);
			
			if (param.vars != null)
				req.data = param.vars
			
			loader.load(req, param.lc);
		}
		
		/**
		 * 进度事件 
		 * @param e
		 * 
		 */		
		private function progressHandler(e:ProgressEvent):void
		{
			var loaderInfo:LoaderInfo = e.target as LoaderInfo;
			var param:getLoaderInfoParam = currentLoader[loaderInfo.loader];
			
			if (param.progressCallback is Function)
				param.progressCallback(e);
		}
		
		/**
		 * 加载失败 
		 * @param e
		 * 
		 */		
		private function errorHandler(e:IOErrorEvent):void
		{
			var loaderInfo:LoaderInfo = e.target as LoaderInfo;
			var param:getLoaderInfoParam = currentLoader[loaderInfo.loader];
			
			trace("DisplayLoader Fail:", param.url);
			
			if (param.failCallback != null)
				param.failCallback(e);
			
			delete currentLoaderUrl[param.url+param.vars];
			delete currentLoader[loaderInfo.loader];
			
			var index:int = urlQueue.indexOf(param.url);
			// 加载下个文件
			if (index != -1)
			{
				urlQueue.splice(index, 1);
				param = valueQueue[index] as getLoaderInfoParam;
				valueQueue.splice(index, 1);
				
				loadFile(param);
			}
		}
		
		/**
		 * 加载成功 
		 * @param e
		 * 
		 */		
		private function completeHandler(e:Event):void
		{
			var loaderInfo:LoaderInfo = e.target as LoaderInfo;
			var param:getLoaderInfoParam = currentLoader[loaderInfo.loader];
			
			if (param.successCallback != null)
            {
                if(param.contextObject != null)
                {
				    param.successCallback(loaderInfo, param.contextObject);
                }
                else
                {
                    param.successCallback(loaderInfo);
                }
            }
			
			delete currentLoaderUrl[param.url+param.vars];
			delete currentLoader[loaderInfo.loader];
			
			var index:int = urlQueue.indexOf(param.url);
			// 加载下个文件
			if (index != -1)
			{
				urlQueue.splice(index, 1);
				param = valueQueue[index] as getLoaderInfoParam;
				valueQueue.splice(index, 1);
				
				loadFile(param);
			}
		}
	}
}


import flash.display.Loader;
import flash.net.URLVariables;
import flash.system.LoaderContext;

class getLoaderInfoParam{
	public var url:String;
	public var successCallback:Function;
    public var contextObject:Object;
	public var failCallback:Function;
	public var progressCallback:Function;
	public var lc:LoaderContext;
	public var vars:URLVariables;
	public var loader:Loader;
}